<template>
  <div>
    <div
      ref="point"
      :class="classes"
      :style="styles"
    >
      <slot></slot>
    </div>
    <div
      v-show="slot"
      :style="slotStyle"
    ></div>
  </div>
</template>
<script>
import { mapState } from "vuex";
const prefixCls = "el-affix";

function getScroll(target, top) {
  const prop = top ? "pageYOffset" : "pageXOffset";
  const method = top ? "scrollTop" : "scrollLeft";

  let ret = target[prop];

  if (typeof ret !== "number") {
    ret = window.document.documentElement[method];
  }

  return ret;
}

function getOffset(element) {
  const rect = element.getBoundingClientRect();

  const scrollTop = getScroll(window, true);
  const scrollLeft = getScroll(window);

  const docEl = window.document.body;
  const clientTop = docEl.clientTop || 0;
  const clientLeft = docEl.clientLeft || 0;

  return {
    top: rect.top + scrollTop - clientTop,
    left: rect.left + scrollLeft - clientLeft
  };
}

export default {
  name: "Affix",
  props: {
    offsetTop: {
      type: Number,
      default: 0
    },
    offsetBottom: {
      type: Number
    }
  },
  data() {
    return {
      affix: false,
      styles: {},
      slot: false,
      slotStyle: {}
    };
  },
  watch: {
    COLLAPSE() {
      this.update();
    }
  },
  computed: {
    offsetType() {
      let type = "top";
      if (this.offsetBottom >= 0) {
        type = "bottom";
      }

      return type;
    },
    classes() {
      return [
        {
          [`${prefixCls}`]: this.affix
        }
      ];
    },
    ...mapState(["COLLAPSE"])
  },
  mounted() {
    this.$nextTick(() => {
      this.update();
    });
    window.addEventListener("scroll", this.update, false);
    window.addEventListener("resize", this.update, false);
  },
  beforeDestroy() {
    window.removeEventListener("scroll", this.update, false);
    window.removeEventListener("resize", this.update, false);
  },
  methods: {
    update() {
      const scrollTop = getScroll(window, true);
      const elOffset = getOffset(this.$el);
      const windowHeight = window.innerHeight;
      const elHeight = this.$el.getElementsByTagName("div")[0].offsetHeight;

      // Fixed Top
      if (
        elOffset.top - this.offsetTop < scrollTop &&
        this.offsetType == "top"
      ) {
        this.affix = true;
        this.slotStyle = {
          width: this.$refs.point.clientWidth + "px",
          height: this.$refs.point.clientHeight + "px"
        };
        this.slot = true;
        this.styles = {
          top: `${this.offsetTop}px`,
          left: `${elOffset.left}px`,
          width: `${this.$el.offsetWidth}px`
        };

        this.$emit("on-change", true);
      } else if (
        elOffset.top - this.offsetTop > scrollTop &&
        this.offsetType == "top"
      ) {
        this.slot = false;
        this.slotStyle = {};
        this.affix = false;
        this.styles = null;

        this.$emit("on-change", false);
      }

      // Fixed Bottom
      if (
        elOffset.top + this.offsetBottom + elHeight >
          scrollTop + windowHeight &&
        this.offsetType == "bottom"
      ) {
        this.affix = true;
        let asideWidth = Number(document.querySelector("aside").style.width.replace("px","")) +57;
        let innerWidth  = window.innerWidth - asideWidth;
        this.styles = {
          bottom: `${this.offsetBottom}px`,
          left: `${elOffset.left}px`,
          width: `${innerWidth}px`
        };

        this.$emit("on-change", true);
      } else if (
        elOffset.top + this.offsetBottom + elHeight <
          scrollTop + windowHeight &&
        this.offsetType == "bottom"
      ) {
        this.affix = false;
        this.styles = null;

        this.$emit("on-change", false);
      }
    }
  }
};
</script>

<style scope lang="scss">
.el-affix {
  position: fixed;
  z-index: 10;
}
</style>

